Decorator Pattern

Dectorator Pattern က Structural Pattern တစ်ခုဖြစ်ပါတယ်။ Dectorator Pattern က proxy နဲ့ ဆင်ပါတယ်။ လက်ရှိ ရှိနေသည့် class အပေါ်က ထပ်ပြီး အုပ်ထားသည့် သဘောပါ။ ဥပမာ Pizza ဆိုရင် base ပေါ်မှာ cheese ထည့်မယ် ခရမ်းချဥ်သီး ထည့်မယ် စသည်ဖြင့် အပေါ်မှာ ထပ်ထပ် ဖြည့်သွားသည့် သဘောမျိုးပါပဲ။

Proxy pattern နဲ့ ဆင်သလို ရှိပေမယ့် အသုံးပြုသည့် အကြောင်းအရာက မတူညီပါဘူး။ Proxy pattern ကတော့ action တစ်ခု မလုပ်ခင်မှာ တစ်ခုခု လုပ်လို့ရအောင် ပြင်လိုက်သည့် သဘောဖြစ်ပြီးတော့ Decorator pattern ကတော့ လက်ရှိ တခြား function တွေ ရအောင် ထပ် အုပ်သည့် သဘောပါ။

ဥပမာ

Notification server အတွက် SMS, Facebook, Slack ဆိုပြီး ရှိပါမယ်။ Notification ကို တစ်ခု ဆီ ပို့ရင် အဆင်ပြေပေမယ့် SMS နဲ့ Facebook တွဲပို့မယ်။ ဒါမှမဟုတ် Facebook နဲ့ Slack ပဲ ပို့မယ် ဆိုရင် အဆင်မပြေတော့ပါဘူး။ အဆင်ပြေအောင် class တွေ အများကြီး ထပ်ခွဲနေရပါမယ်။

ဒီလို class တွေ ခွဲထုတ်တာ အဆင်ပြေပေမယ့် Open Close Principle ကို မလိုက်နာတော့ပါဘူး။

Decorator pattern ပြန် သုံးမယ် ဆိုရင် အောက်ပါအတိုင်း ပြင်ပါမယ်။

ဒီ မှာဆိုရင် SMS, Facebook, Slack တွေက decorator ဖြစ်သွားပြီး send လုပ်သည့်အခါမှာ parent ရဲ့ send ကို ခေါ်ပြီးမှ သက်ဆိုင်ရာ ကို class ရဲ့ send ကို ခေါ်ပါမယ်။

Code level မှာ ရေးမယ် ဆိုရင် အောက်ပါ code အတိုင်း ဖြစ်ပါမယ်။

stack = new Notifier();
if(smsOn) {
    stack = new SMSDecorator(stack);
}
if(facebookOn) {
    stack = new FacebookDecorator(stack);
}
if(slackOn) {
    stack = new SlackDecorator(stack);
}
sendNotification(stack);
//it will send SMS -> Facebook -> Slack

Decorator pattern နဲ့ Code အရှည်ကို ကြည့်ရအောင်။

Notifier.java

// Notifier class
public interface Notifier {
    public void send(String message);
}

BaseDecorator.java

// BaseDecorator class
public class BaseDecorator implements Notifier {
    private Notifier wrap;

    public BaseDecorator(Notifier wrap) {
        this.wrap = wrap;
    }

    public void send(String message) {
        // Call the wrapped Notifier's send method
        wrap.send(message);
    }
}

SMSDecorator.java

// SMSDecorator class
public class SMSDecorator extends BaseDecorator {
    public SMSDecorator(Notifier wrap) {
        super(wrap);
    }

    @Override
    public void send(String message) {
        // Call the wrapped Notifier's send method
        super.send(message);
        
        // Implement additional functionality for sending an SMS
        sendSMS(message);
    }

    private void sendSMS(String message) {
        // Implementation for sending an SMS
    }
}

FacebookDecorator.java

// FacebookDecorator class
public class FacebookDecorator extends BaseDecorator {
    public FacebookDecorator(Notifier wrap) {
        super(wrap);
    }

    @Override
    public void send(String message) {
        // Call the wrapped Notifier's send method
        super.send(message);
        
        // Implement additional functionality for sending a Facebook message
        sendToFacebook(message);
    }

    private void sendToFacebook(String message) {
        // Implementation for sending a message to Facebook
    }
}

SlackDecorator.java

// SlackDecorator class
public class SlackDecorator extends BaseDecorator {
    public SlackDecorator(Notifier wrap) {
        super(wrap);
    }

    @Override
    public void send(String message) {
        // Call the wrapped Notifier's send method
        super.send(message);
        
        // Implement additional functionality for sending a Slack message
        sendToSlack(message);
    }

    private void sendToSlack(String message) {
        // Implementation for sending a message to Slack
    }
}

Application.java

public class Application {
    public static void main(String[] args) {
       

        Notifier smsNotifier = new SMSDecorator(null);
        Notifier facebookNotifier = new FacebookDecorator(smsNotifier);
        Notifier slackNotifier = new SlackDecorator(facebookNotifier);

        String message = "Hello, World!";
        slackNotifier.send(message);
    }
}

Code မှာ ရေးထားသည့် အတိုင်း send ကို မခေါ်ခင်မှာ သူ့အပေါ်က class ရဲ့ send ကိုအရင် ခေါ်ပြီး အလုပ်လုပ်သွားတာ တွေ့နိုင်ပါတယ်။

Proxy Pattern နဲ့ Decorator Pattern ဆင်ပါတယ် ။ ဒါပေမယ့် ရည်ရွယ်ချက်ခြင်း မတူတာကို တွေ့နိုင်တယ်။ Proxy Pattern ဟာ ကြားခံ လုပ်ဆောင်ဖို့ ဖန်တီး တာ ဖြစ်ပြီး decorator pattern က တော့ beahvior အသစ် အပေါ်မှာ ထပ်ပြီး အုပ်ထားတာ ဖြစ်ပါတယ်။

Pros and Cons

Class တွေကို ထပ်ကာထပ်ကာ extend လုပ်ပြီး အသုံးပြုနိုင်ပါတယ်။

Runtime မှာ responsiblity တွေကို ပြင်လို့ ရတယ်။

Single Responsibility Principle ကို လိုက်နာထားတယ်။

မကောင်းတာကတော့ ဘယ် wrapper ကို မသုံးတော့ဘူး ဆိုပြီး ဖယ်ထုတ်လိုက်ဖို့ ခက်ပါတယ်။

Class ဖန်တီးရတာ နည်းနည်း ခက်ခဲမှုရှိနိုင်တယ်။ Class က layers တွေ ထပ်ကာ ထပ်ကာ ရှိပြီး ရိုးရှင်းမှု ရှိမနေပါဘူး။